/**
 *	@class			Jx.data.Model
 *	@description	creates record instance
 *						models the data from a result
 */
Jx.declare('Jx.data.Model', {

	$extend: 'Jx.Base',

	$requires: [

		'Jx.lib.Hash',

		'Jx.data.Manager',

		'Jx.data.Field'

	],

	$actions: [

		'setValue'

	],

	$cascadeCallback: function(Class, Base){

		var classFields = Class.prototype.fields,

			baseTypeClass = 'Jx.lib.Unit',

			fields = Jx.instantiate('Jx.lib.Hash'),

			definedFields = [],

			indexes = Class.$dataIndex = Jx.instantiate('Jx.lib.Hash'),

			baseIndex = Base.$dataIndex,

			primary = void(0),

			basePrimary = void(0);

		//-- auto inherit fields
		if (Jx.isArray(classFields)){

			for(var field, config, name, index, c = 0, l = classFields.length; c < l; c++){

				config = classFields[c];

				if (Jx.isObject(config) &&

					Jx.isString(name = config.name, true)

				){

					fields.set(name,

						field = Jx.instantiate(Class.prototype.fieldClass, [config])

					);

				}

			}

		}

		Class.prototype.fields = fields.applyIf( Base.prototype.fields );


		//-- register to Manager
		Jx.data.Manager.registerModel(Class.$name);

	},

	$static: {

		declare: function(name, properties, publicized){

			if (Jx.isString(name, true) && Jx.isObject(properties)){

				if (!Jx.isString(properties.$extend, true)){

					properties.$extend = this.$name;

				}

				Jx[

					publicized !== false ?

						'declare'

						:

						'categorize'

				]( name, properties );

			}

		},

		createPseudoModel: function(models){

			var fields = [];

			//-- create fields
			for(var model, currentFields, c=0, l = models.length; c<l; c++){

				currentFields = (model = model[l]).prototype.fields;

				for(var field, fl = currentFields.length; fl--;){

					field = currentFields[fl];

				}

			}


		},

		getFields: function(){

			return this.prototype.fields;

		}

	},


	$shortcuts: {

		'Jx': {

			'createModel': 'declare'

		}

	},

	fields: [],

	fieldClass: 'Jx.data.Field',

	dataSource: undefined,

	constructor: function(data){

		//-- initialize values
		this.initializeValues();

		this.$super(arguments);

	},

	initializeValues: function(){

		for(var fields = this.fields, l = fields.length; l--;){

			fields.get( fields[l] ).initializeValue( this );

		}

	},

	getValue: function(name){

		var field = this.fields.get(name),

			value = this.get(name);

		return field ?

			value[ field.getterMethod() ].apply( value, field.getterParams() || [] )

			:

			value;

	},

	onSetValue: function(operation, name, value){

		var field = operation.field,

			unit = operation.unit;

		if ( this.fields.isSet(name) ){

			this.get(name).setValue(value);

			operation.value = this.getValue(name);

		} else {

			this.set(value);

		}

	},

	onAfterSetValue: function(operation, name){

		this.dispatch( 'update', name, operation.value, operation.old );

	},

	allowSetValue: function(operation, name, value){

		var allow = Jx.isString(name, true);

		if (allow){

			operation.old = this.getValue(name);

			operation.value = value;

		}

		return allow;

	},

	compare: function(name, value){

		var myValue = this.get(name);

		if (this.fields.isSet(name)){

			return myValue.compare(value);

		} else {

			myValue = String(myValue);

			value = String(value);

			return  myValue == value ?

				0

				:

				myValue < value ?

					-1

					:

					1;

		}

	}






});
